package reflection;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;

/**
 * bean工具类.
 * 该工具依赖apache beanutils
 *
 * @author guanweichen
 * @version 2010-7-19
 */
public class BeanUtils {

    /**
     * 对bean中的String类型的属性进行去掉左右空格操作.
     * 
     * @param <T> 操作的类范型
     * @param object 操作对象
     * @param clazz 操作对象的类
     * @return 返回操作后的对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T trimPropertiesForTypeString(Object object, Class<T> clazz) {

        Map<String, Class> mapProperties = ReflectionUtil.getAllProperties(clazz);
        for (String propName : mapProperties.keySet()) {
            Class propType = mapProperties.get(propName);
            Object prop;
            if (propType.equals(String.class)) {
                Method readMethod = ReflectionUtil.getReadMethod(propName, clazz);
                Method writeMethod = ReflectionUtil.getWriteMethod(propName, clazz);
                try {
                    prop = readMethod.invoke(object, null);
                    if (null != prop) {
                        writeMethod.invoke(object, prop.toString().trim());
                    }
                } catch (Exception e) {
                    throw new RuntimeException("反射异常,执行Read方法或者write方法失败", e);
                }
            }
        }
        return (T) object;
    }
    
    /**
     * 复制指定的属性，没指定复制全部.
     * 
     * @param src
     * @param dest
     * @param properties
     */
    public static void copyProperties(Object src, Object dest, String... properties) {

        try {
            if (properties == null || properties.length == 0) {
                PropertyUtils.copyProperties(src, dest);
            } else {
                for (String propName : properties) {
                    Object value = PropertyUtils.getProperty(src, propName);
                    PropertyUtils.setProperty(dest, propName, value);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("属性复制失败", e);
        }
    }
    
    /**
     * 把map中 key 的名称与bean 中的属性名称相同的属性的值赋值给bean 的该属性.
     * 
     * @param <T>
     * @param propties
     * @param t
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T setMapToPropties(Map<?, ?> propties, T t) {

        Map<String, Class> propMap = ReflectionUtil.getAllProperties(t.getClass());
        for (Object propName : propties.keySet()) {
            for (String propToName : propMap.keySet()) {
                if (propToName.equals(propName.toString()) && propties.get(propName) != null) {
                    try {
                        org.apache.commons.beanutils.BeanUtils.setProperty(t, propToName,
                                propties.get(propName));
                    } catch (Exception e) {
                        try {
                            org.apache.commons.beanutils.BeanUtils.setProperty(
                                    t,
                                    propToName,
                                    new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(propties.get(
                                            propName).toString()));
                        } catch (Exception e1) {
                            try {
                                org.apache.commons.beanutils.BeanUtils.setProperty(
                                        t,
                                        propToName,
                                        new SimpleDateFormat("yyyy-MM-dd").parse(propties.get(
                                                propName).toString()));
                            } catch (Exception e2) {
                                throw new RuntimeException(e2.getMessage(), e2);
                            }
                        }
                    }
                }
            }
        }
        return t;
    }
    
    /**
     * 根据属性名称执行read.
     * 
     * @param propName
     * @param bean
     * @return
     */
    public static Object invokeReadMethod(String propName, Object bean) {

        Method reader = ReflectionUtil.getReadMethod(propName, bean.getClass());
        try {
            return reader.invoke(bean, null);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
}
